using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Timers;
using Newtonsoft.Json;

namespace BanZuiCloudControlAgent.Utils.Logging
{
    /// <summary>
    /// 日志上传器，负责将本地日志上传到远程服务器
    /// </summary>
    public class LogUploader
    {
        private readonly string _serverUrl;
        private readonly string _agentName;
        private readonly string _secretKey;
        private readonly Timer _uploadTimer;
        private readonly Logger _logger;
        private readonly Queue<UploadLogEntry> _pendingLogs;
        private readonly object _lockObject = new object();
        private bool _isUploading = false;
        private readonly int _maxRetryCount = 3;
        private readonly int _maxBatchSize = 100;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="serverUrl">服务器URL</param>
        /// <param name="agentName">代理名称</param>
        /// <param name="secretKey">密钥</param>
        /// <param name="uploadIntervalSeconds">上传间隔（秒）</param>
        public LogUploader(string serverUrl, string agentName, string secretKey, int uploadIntervalSeconds = 60)
        {
            _serverUrl = serverUrl;
            _agentName = agentName;
            _secretKey = secretKey;
            _logger = LogManager.GetLogger("LogUploader");
            _pendingLogs = new Queue<UploadLogEntry>();

            // 设置定时上传
            _uploadTimer = new Timer(uploadIntervalSeconds * 1000);
            _uploadTimer.Elapsed += OnUploadTimerElapsed;
            _uploadTimer.AutoReset = true;
        }

        /// <summary>
        /// 启动日志上传服务
        /// </summary>
        public void Start()
        {
            _uploadTimer.Start();
            _logger.Info("日志上传服务已启动");
        }

        /// <summary>
        /// 停止日志上传服务
        /// </summary>
        public void Stop()
        {
            _uploadTimer.Stop();
            _logger.Info("日志上传服务已停止");
        }

        /// <summary>
        /// 添加日志条目到上传队列
        /// </summary>
        /// <param name="logEntry">日志条目</param>
        public void EnqueueLog(UploadLogEntry logEntry)
        {
            lock (_lockObject)
            {
                _pendingLogs.Enqueue(logEntry);
            }
        }

        /// <summary>
        /// 批量添加日志条目到上传队列
        /// </summary>
        /// <param name="logEntries">日志条目集合</param>
        public void EnqueueLogs(IEnumerable<UploadLogEntry> logEntries)
        {
            lock (_lockObject)
            {
                foreach (var entry in logEntries)
                {
                    _pendingLogs.Enqueue(entry);
                }
            }
        }

        /// <summary>
        /// 定时器触发事件，执行日志上传
        /// </summary>
        private void OnUploadTimerElapsed(object sender, ElapsedEventArgs e)
        {
            UploadPendingLogsAsync().ConfigureAwait(false);
        }

        /// <summary>
        /// 立即上传所有待处理的日志
        /// </summary>
        public async Task UploadPendingLogsAsync()
        {
            if (_isUploading)
                return;

            try
            {
                _isUploading = true;
                
                List<UploadLogEntry> batchLogs;
                lock (_lockObject)
                {
                    if (_pendingLogs.Count == 0)
                        return;

                    // 取出一批日志进行上传
                    int count = Math.Min(_pendingLogs.Count, _maxBatchSize);
                    batchLogs = new List<UploadLogEntry>(count);
                    for (int i = 0; i < count; i++)
                    {
                        batchLogs.Add(_pendingLogs.Dequeue());
                    }
                }

                _logger.Debug($"准备上传{batchLogs.Count}条日志");
                bool success = false;
                int retryCount = 0;

                while (!success && retryCount < _maxRetryCount)
                {
                    try
                    {
                        success = await UploadLogsAsync(batchLogs);
                        if (success)
                        {
                            _logger.Info($"成功上传{batchLogs.Count}条日志");
                        }
                        else
                        {
                            retryCount++;
                            _logger.Warn($"日志上传失败，准备第{retryCount}次重试");
                            await Task.Delay(2000 * retryCount); // 延迟重试
                        }
                    }
                    catch (Exception ex)
                    {
                        retryCount++;
                        _logger.Error($"日志上传异常，准备第{retryCount}次重试", ex);
                        await Task.Delay(2000 * retryCount); // 延迟重试
                    }
                }

                if (!success)
                {
                    _logger.Error($"日志上传失败，已达到最大重试次数{_maxRetryCount}，放弃上传");
                    // 重新将失败的日志放回队列
                    lock (_lockObject)
                    {
                        foreach (var entry in batchLogs)
                        {
                            _pendingLogs.Enqueue(entry);
                        }
                    }
                }
            }
            finally
            {
                _isUploading = false;
            }
        }

        /// <summary>
        /// 上传日志到服务器
        /// </summary>
        /// <param name="logs">日志条目集合</param>
        /// <returns>是否上传成功</returns>
        private async Task<bool> UploadLogsAsync(List<UploadLogEntry> logs)
        {
            using (HttpClient client = new HttpClient())
            {
                // 准备上传数据
                var uploadData = new
                {
                    AgentName = _agentName,
                    SecretKey = _secretKey,
                    Timestamp = ((DateTimeOffset)DateTime.UtcNow).ToUnixTimeSeconds(),
                    Logs = logs
                };

                var json = JsonConvert.SerializeObject(uploadData);
                var content = new StringContent(json, Encoding.UTF8, "application/json");

                // 设置超时时间
                client.Timeout = TimeSpan.FromSeconds(30);

                // 发送请求
                var response = await client.PostAsync($"{_serverUrl}/api/logs/upload", content);
                
                // 检查响应
                return response.IsSuccessStatusCode;
            }
        }

        /// <summary>
        /// 从本地日志文件中读取并上传日志
        /// </summary>
        /// <param name="logFilePath">日志文件路径</param>
        /// <returns>是否上传成功</returns>
        public async Task<bool> UploadLogFileAsync(string logFilePath)
        {
            try
            {
                if (!File.Exists(logFilePath))
                {
                    _logger.Error($"日志文件不存在: {logFilePath}");
                    return false;
                }

                _logger.Info($"开始上传日志文件: {logFilePath}");

                // 读取日志文件内容
                string logContent = File.ReadAllText(logFilePath);

                // 解析日志内容为UploadLogEntry对象（这里需要根据实际日志格式进行解析）
                var logEntries = ParseLogFile(logContent);

                // 批量上传日志
                EnqueueLogs(logEntries);
                await UploadPendingLogsAsync();

                return true;
            }
            catch (Exception ex)
            {
                _logger.Error($"上传日志文件失败: {logFilePath}", ex);
                return false;
            }
        }

        /// <summary>
        /// 解析日志文件内容为UploadLogEntry对象
        /// </summary>
        /// <param name="logContent">日志文件内容</param>
        /// <returns>日志条目集合</returns>
        private List<UploadLogEntry> ParseLogFile(string logContent)
        {
            var result = new List<UploadLogEntry>();
            
            // 按行分割日志内容
            string[] lines = logContent.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
            
            foreach (var line in lines)
            {
                try
                {
                    // 解析日志行（示例格式：2023-06-30 12:34:56.789 | INFO | Logger | Message）
                    var parts = line.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
                    if (parts.Length >= 4)
                    {
                        DateTime timestamp;
                        if (DateTime.TryParse(parts[0].Trim(), out timestamp))
                        {
                            var levelStr = parts[1].Trim();
                            var logger = parts[2].Trim();
                            var message = parts[3].Trim();
                            
                            // 解析日志级别
                            LogSeverity level = LogSeverity.Info; // 默认为Info级别
                            if (Enum.TryParse<LogSeverity>(levelStr, true, out LogSeverity parsedLevel))
                            {
                                level = parsedLevel;
                            }
                            
                            // 创建日志条目
                            var logEntry = new UploadLogEntry
                            {
                                Timestamp = timestamp,
                                Level = level,
                                Logger = logger,
                                Message = message
                            };
                            
                            result.Add(logEntry);
                        }
                    }
                }
                catch (Exception ex)
                {
                    _logger.Warn($"解析日志行失败: {line}", ex);
                    // 继续处理下一行
                }
            }
            
            return result;
        }
    }

    /// <summary>
    /// 日志条目，用于上传到服务器
    /// </summary>
    public class UploadLogEntry
    {
        /// <summary>
        /// 时间戳
        /// </summary>
        public DateTime Timestamp { get; set; }
        
        /// <summary>
        /// 日志级别
        /// </summary>
        public LogSeverity Level { get; set; }
        
        /// <summary>
        /// 日志记录器名称
        /// </summary>
        public string Logger { get; set; }
        
        /// <summary>
        /// 日志消息
        /// </summary>
        public string Message { get; set; }
        
        /// <summary>
        /// 异常信息（可选）
        /// </summary>
        public string Exception { get; set; }
    }

    /// <summary>
    /// 日志级别枚举
    /// </summary>
    public enum LogSeverity
    {
        Debug,
        Info,
        Warning,
        Error,
        Fatal
    }
} 